#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sikle.h"

void SAnonymousWord_push(SikleState* ss, Stacel* stacel)
{
  ExecStack* es = ss->exec_stack;
  void* sp = es->base + es->sp;

  // printf("SAnonymousWord_push(base:%p,sp:%d)\n", es->base, es->sp);

  if(stacel->type == STACEL_ANONYMOUS_WORD) {
    *(SAnonymousWord*)sp = *(SAnonymousWord*)stacel;
    sp += sizeof(SAnonymousWord);
    STACEL(sp)->type = STACEL_ANONYMOUS_WORD;
    es->sp += sizeof(SAnonymousWord) + sizeof(Stacel);
  }
  else {
    log_msg(LOG_ERROR, "SAnonymousWord_push error", NULL);
  }
}

void SAnonymousWord_pop(SikleState* ss, Stacel* stacel)
{
  ExecStack* es = ss->exec_stack;
  void* sp = es->base + es->sp - sizeof(Stacel);
  
  if(STACEL(sp)->type == STACEL_ANONYMOUS_WORD) {
    sp -= sizeof(SAnonymousWord);
    *(SAnonymousWord*)stacel = *(SAnonymousWord*)sp;
    es->sp = sp - es->base;
  }
  else {
    log_msg(LOG_ERROR, "SAnonymousWord_pop error", NULL);
  }
}

void SAnonymousWord_drop(SikleState* ss)
{
  ExecStack* es = ss->exec_stack;
  void* sp = es->base + es->sp - sizeof(Stacel);
  
  if(STACEL(sp)->type == STACEL_ANONYMOUS_WORD) {
    es->sp -= sizeof(SAnonymousWord) + sizeof(Stacel);
  }
  else {
    log_msg(LOG_ERROR, "SAnonymousWord_drop error", NULL);
  }
}

void SAnonymousWord_dup(SikleState* ss)
{
  SAnonymousWord word;
  ExecStack* es = ss->exec_stack;
  void* sp = es->base + es->sp - sizeof(Stacel);

  if(STACEL(sp)->type == STACEL_ANONYMOUS_WORD) {
    sp -= sizeof(SAnonymousWord);
    word = *(SAnonymousWord*)sp;

    sp = es->base + es->sp;
    *(SAnonymousWord*)sp = word;
    sp += sizeof(SAnonymousWord);
    STACEL(sp)->type = STACEL_ANONYMOUS_WORD;
    es->sp += sizeof(SAnonymousWord) + sizeof(Stacel);
  }
  else {
    log_msg(LOG_ERROR, "SAnonymousWord_dup error", NULL);
  }
}

void SAnonymousWord_p(SikleState* ss)
{
  SAnonymousWord word;
  ExecStack* es = ss->exec_stack;
  void* sp = es->base + es->sp - sizeof(Stacel);

  if(STACEL(sp)->type == STACEL_ANONYMOUS_WORD) {
    sp -= sizeof(SAnonymousWord);
    word = *(SAnonymousWord*)sp;

    printf("@(%p:%d)", ss->word_pool, word.entry);
  }
  else {
    log_msg(LOG_ERROR, "SAnonymousWord_p error", NULL);
  }
}

StacelOperation anonymous_word_ops = {
  .push = SAnonymousWord_push,
  .pop = SAnonymousWord_pop,
  .drop = SAnonymousWord_drop,
  .dup = SAnonymousWord_dup,

  .clone = NULL,

  .to_integer = NULL,
  .to_string = NULL,
  .to_boolean = NULL,

  .p = SAnonymousWord_p,

  .add = NULL,
  .sub = NULL,
  .mul = NULL,
  .div = NULL
};
